package arithmetic;


import java.util.Scanner;

/**
 * HJ18识别有效的IP地址和掩码并进行分类统计
 * 知识点：
 * 1.数值型转二进制
 * 2.String.startsWith();
 * 3.String.lastIndexOf();
 * 4.String.subString();
 * 5.重点理解：
 *  子网掩码为二进制下前面是连续的1，然后全是0。（例如：255.255.255.32就是一个非法的掩码）
 *  * （注意二进制下全是1或者全是0均为非法子网掩码）
 *  示例：255.128.0.0是一个合法的掩码
 * 描述
 * 请解析IP地址和对应的掩码，进行分类识别。要求按照A/B/C/D/E类地址归类，不合法的地址和掩码单独归类。
 *
 * 所有的IP地址划分为 A,B,C,D,E五类
 *
 * A类地址从1.0.0.0到126.255.255.255;
 *
 * B类地址从128.0.0.0到191.255.255.255;
 *
 * C类地址从192.0.0.0到223.255.255.255;
 *
 * D类地址从224.0.0.0到239.255.255.255；
 *
 * E类地址从240.0.0.0到255.255.255.255
 *
 *
 * 私网IP范围是：
 *
 * 从10.0.0.0到10.255.255.255
 *
 * 从172.16.0.0到172.31.255.255
 *
 * 从192.168.0.0到192.168.255.255
 *
 *
 * 子网掩码为二进制下前面是连续的1，然后全是0。（例如：255.255.255.32就是一个非法的掩码）
 * （注意二进制下全是1或者全是0均为非法子网掩码）
 *
 * 注意：
 * 1. 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类，也不属于不合法ip地址，计数时请忽略
 * 2. 私有IP地址和A,B,C,D,E类地址是不冲突的
 *
 * 输入描述：
 * 多行字符串。每行一个IP地址和掩码，用~隔开。
 *
 * 请参考帖子https://www.nowcoder.com/discuss/276处理循环输入的问题。
 * 输出描述：
 * 统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数，之间以空格隔开。
 *
 * 示例1
 * 输入：
 * 10.70.44.68~255.254.255.0
 * 1.0.0.1~255.0.0.0
 * 192.168.0.2~255.255.255.0
 * 19..0.~255.255.255.0
 * 复制
 * 输出：
 * 1 0 1 0 0 2 1
 * 复制
 * 说明：
 * 10.70.44.68~255.254.255.0的子网掩码非法，19..0.~255.255.255.0的IP地址非法，所以错误IP地址或错误掩码的计数为2；
 * 1.0.0.1~255.0.0.0是无误的A类地址；
 * 192.168.0.2~255.255.255.0是无误的C类地址且是私有IP；
 * 所以最终的结果为1 0 1 0 0 2 1
 * 示例2
 * 输入：
 * 0.201.56.50~255.255.111.255
 * 127.201.56.50~255.255.111.255
 * 复制
 * 输出：
 * 0 0 0 0 0 0 0
 * 复制
 * 说明：
 * 类似于【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类，也不属于不合法ip地址，计数时请忽略
 */
public class TestHW18 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        // while (in.hasNextInt()) { // 注意 while 处理多个 case
        //     int a = in.nextInt();
        //     int b = in.nextInt();
        //     System.out.println(a + b);
        // }
        //获取所有的输入
        String input = getAllInput(in);
        // System.out.println(input);
        if (input.isEmpty()) {
            System.out.println("0 0 0 0 0 0 0");
            return;
        };
        //筛选掉格式不匹配的数据
        String input1 = test(input);
        int err = input.split(";").length - input1.split(";").length;
        if (input1.isEmpty()) {
            System.out.println("0 0 0 0 0 " + err + " 0");
            return;
        };
        // System.out.println(input1);
        //筛选掉0.和127.开头的数据
        String input2 = test3(input1);
        if (input2.isEmpty()) {
            System.out.println("0 0 0 0 0 " + err + " 0");
            return;
        };
        // System.out.println(input2);
        //筛选掉掩码不合格的数据
        String input3 = test4(input2);
        err += input2.split(";").length - input3.split(";").length;
        if (input3.isEmpty()) {
            System.out.println("0 0 0 0 0 " + err + " 0");
            return;
        }
        //统计
        int a = test5(input3, 1, 126);
        int b = test5(input3, 128, 191);
        int c = test5(input3, 192, 223);
        int d = test5(input3, 224, 239);
        int e = test5(input3, 240, 255);
        int p = test6(input3);
        System.out.println(a + " " + b + " " + c + " " + d + " " + e + " " + err + " " +
                p);
    }
    //筛选私有
    public static int test6(String input) {
        int count = 0;
        String[] inputs = input.split(";");
        int index = 0;
        while (index < inputs.length) {
            String str = inputs[index];
            String[] strs = str.split("~");
            String str0 = strs[0];
            if (str0.startsWith("10.") || str0.startsWith("192.168.")) {
                count++;
            }
            if (str0.startsWith("172.")) {
                String[] str0s = str0.split("\\.");
                int num = Integer.parseInt(str0s[1]);
                if (num >= 16 && num <= 31 && str0.startsWith("172." + num + ".")) {
                    count++;
                }
            }
            index++;
        }
        return count;
    }
    //筛选ABCDE
    public static int test5(String input, int small, int large) {
        int count = 0;
        String[] inputs = input.split(";");
        // System.out.println(input+"长度："+inputs.length);
        for (int i = 0; i < inputs.length; i++) {
            String str = inputs[i];
            // System.out.println(str);
            String[] strs = str.split("~");
            String strss = strs[0];
            String[] strs2 = strss.split("\\.");
            String str2 = strs2[0];
            int num = Integer.parseInt(str2);
            if (num >= small && num <= large && strss.startsWith(num + ".")) {
                // System.out.println(num);
                count++;
                // System.out.println(str);
            }
        }
        return count;
    }
    //筛选掉掩码不合格的数据
    public static String test4(String input) {
        String strInput = "";
        String[] inputs = input.split(";");
        for (int i = 0; i < inputs.length; i++) {
            String str = inputs[i];
            String[] strs = str.split("~");
            String subStr2 = strs[1];
            String[] subStr2s = subStr2.split("\\.");
            int num1 = Integer.parseInt(subStr2s[0]);
            int num2 = Integer.parseInt(subStr2s[1]);
            int num3 = Integer.parseInt(subStr2s[2]);
            int num4 = Integer.parseInt(subStr2s[3]);
            String subStrEr = test41(num1) + test41(num2) + test41(num3) + test41(num4);
            int index = subStrEr.lastIndexOf("1");
            boolean f1 = !subStrEr.substring(0, index+1).contains("0");
            boolean f2 = index != 31;
            if (f1 && f2) {
                strInput += str + ";";
            }
        }
        return strInput;
    }

    //数字转二进制
    public static String test41(int num) {
        String str = "";
        int index = 7;
        while (index > -1) {
            int n = (int)Math.pow(2, index);
            if (n > num) {
                str += "0";
            }
            if (n <= num) {
                str += "1";
                num = num - n;
            }
            index--;
        }
        return str;
    }

    //筛选掉0.和127.开头的数据
    public static String test3(String input) {
        String strInput = "";
        String[] inputs = input.split(";");
        int index = 0;
        while (index < inputs.length) {
            String str = inputs[index];
            if (!(str.startsWith("0.") || str.startsWith("127."))) {
                strInput += str + ";";
            }
            index++;
        }
        return strInput;
    }


    //筛选格式不匹配的数据
    public static String test(String input) {
        String strInput = "";
        String[] inputs = input.split(";");
        //筛选条件一
        for (int i = 0; i < inputs.length; i++) {
            String str = inputs[i];
            String[] strs = str.split("~");
            if (strs.length == 2) {
                strInput += str + ";";
            }
        }
        //筛选条件二
        inputs = strInput.split(";");
        strInput = "";
        for (int i = 0; i < inputs.length; i++) {
            String str = inputs[i];
            String[] strs = str.split("~");
            int len1 = strs[0].split("\\.").length;
            int len2 = strs[1].split("\\.").length;
            if (len1 == 4 && len2 == 4) {
                strInput += str + ";";
            }
        }
        //筛选条件三
        inputs = strInput.split(";");
        strInput = "";
        for (int i = 0; i < inputs.length; i++) {
            String str = inputs[i];
            String[] strs = str.split("~");
            String subStr1 = strs[0];
            String subStr2 = strs[1];
            boolean f = test2(subStr1) && test2(subStr2);
            if (f) {
                strInput += str + ";";
            }
        }
        return strInput;
    }
    //筛选条件三
    public static boolean test2(String subStr) {
        String[] subStrs = subStr.split("\\.");
        boolean f1 = true;
        for (int i = 0; i < subStrs.length; i++) {
            try {
                String sub = subStrs[i];
                if (sub.startsWith("0") && sub.length() > 1) {
                    f1 = false;
                    break;
                }
                int num = Integer.parseInt(sub);
                if (num < 0 || num > 255) {
                    f1 = false;
                    break;
                }
            } catch (Exception e) {
                f1 = false;
                break;
            }
        }
        return f1;

    }
    //获取所有的输入
    public static String getAllInput(Scanner in) {
        String input = "";
        while (in.hasNextLine()) {
            input += in.nextLine() + ";";
        }
        return input;
    }

}
